#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import logging, traceback
import socket
import time
import urlparse

from tornado.escape import utf8, native_str, parse_qs_bytes
from tornado import httputil
from tornado import iostream
from tornado.netutil import TCPServer
from tornado import stack_context
from tornado.util import b, bytes_type
from tornado import ioloop
import struct
import log

try:
    import ssl # Python 2.6+
except ImportError:
    ssl = None
    
    
logger = logging.getLogger(__name__)

class GameServer(TCPServer):    
    def __init__(self, request_callback=None, close_callback=None, io_loop=None, ssl_options=None, **kwargs):
        self.request_callback = request_callback
        self.close_callback = close_callback
        TCPServer.__init__(self, io_loop=io_loop, ssl_options=ssl_options, **kwargs)

    def handle_stream(self, stream, address):
        conn = TCPConnection(stream, address, self.request_callback, self.close_callback)

		
class TCPConnection(object):
    def __init__(self, stream, address, request_callback, close_callback):        
        self.stream = stream
        if self.stream.socket.family not in (socket.AF_INET, socket.AF_INET6):
            address = ('0.0.0.0', 0)
            
        self.address = address
        self.ip = self.address[0]
        self.socket_id = self.stream.socket.fileno() #self.address[1]
        
        self.request_callback = request_callback	#请求回调
        self.close_callback = close_callback		#关闭回调
        self.stream.set_close_callback(self._on_close)
        
        self._request = None		#GameRequest对象

        self._header_callback = stack_context.wrap(self._on_headers)
        self._write_callback = None
        
        self.m_reading = False
        
        self.read()

    def read(self):
        if not self.stream.closed() and not self.stream.reading() and not self.m_reading:
            self.m_reading = True
            self.stream.read_bytes(4, self._header_callback)
    
    def reRead(self):
        self.m_reading = False
        self.read()    
            

    def write(self, chunk, cmd='', callback=None):            
        if not self.stream.closed():            
            log.print_info(logger, "======TCPConnection write,[0] cmd:[%s], IP:[%s] socket:[%s] chunk:\n%s" 
                           % (cmd, self.ip, self.socket_id, chunk))
                     
            self._write_callback = stack_context.wrap(callback)
            self.stream.write(chunk, self._on_write_complete)

    def finish(self):
        self.read()
            
    def close(self):
        self.stream.close()

    def _on_write_complete(self):
        if self._write_callback:
            callback = self._write_callback
            self._write_callback = None
            callback()
        self.read()		#发送完, 重新设置读状态

    def _on_headers(self, data):
        try:          
            if data == '<pol':              
                self.stream.read_until('request/>', self._on_auth_over)                
            else:               
                content_length = struct.unpack('I',data)[0] 
                if content_length:
                    tmpLen = int(content_length)
                    self.stream.read_bytes(tmpLen, self._on_request_body)
        except Exception: 
            log.print_error(logger, '======TCPConnection _on_headers error, IP:[%s] socket:[%s], error info:\n%s' 
                            % (self.ip, self.socket_id, traceback.format_exc()))            
            self.stream.close()
            
    def _on_auth_over(self,data):
        tmpWriteCallback = self.stream.close
        self.write("<cross-domain-policy><allow-access-from domain='*' to-ports='*' /></cross-domain-policy>\0", callback=tmpWriteCallback)
       
    def _on_request_body(self, data):  
        try:
            spaceIndex = data.index(" ")
            cmd = data[0: spaceIndex]
            content = data[spaceIndex+1: ]
            
            #tmpData = data.split(" ")            
            #cmd = tmpData[0] 
            #content = ''.join(tmpData[1:])
            
            log.print_info(logger, "======TCPConnection _on_request_body exec, IP:[%s] socket:[%s]: \nrecvData:%s \tcmd:%s, \tcontent:%s" 
                           % (self.ip, self.socket_id, data, cmd, content))
            
            if self._request is None:
				self._request = GameRequest(self)
            self._request.body = data
            self._request.cmd = cmd
            self._request.content = content
            
            self.request_callback(self._request)    #读 回调
            
            self.reRead() #读取完后重新设为可读
            
        except Exception:
            log.print_error(logger, '======TCPConnection _on_request_body error, IP:[%s] socket:[%s], error info:\n%s' 
                            % (self.ip, self.socket_id, traceback.format_exc()))        
        
    def _on_close(self):
        log.print_info(logger, "======TCPConnection _on_close exec, IP:[%s] socket:[%s]" % (self.ip, self.socket_id))
        self.close_callback(self)
        
class GameRequest(object):
    def __init__(self, connection):
        self.body = ""
        self.cmd = ""
        self.content = ""
        
        self.remote_ip = connection.ip                      #对方IP
        self.socket_id = connection.socket_id #address[1]   #socketID 
        self.connection = connection                        #连接对象
        
    def write(self, chunk, cmd='', callback=None):
        if not cmd:
            cmd = self.cmd
        tmpContent = cmd + " " + chunk
        contentLenth = struct.pack('I',len(tmpContent))
        fullContent = contentLenth + tmpContent
        self.connection.write(fullContent, cmd, callback)

    def finish(self):
        self.connection.finish()
        
    def close(self):
        self.connection.close()

    
#http_server = GameServer()
#http_server.listen(8888)
#ioloop.IOLoop.instance().start()